using System;
using System.Collections;
using System.Text;
using System.Web.UI;

namespace Edge.Common.Web.DataSourceAdapters
{
    public abstract class BaseDataSourceView : DataSourceView
    {

        public class PreSelectEventArgs : EventArgs
        {
            private FetchOptions fetchOptions;


            public PreSelectEventArgs(FetchOptions fetchOptions)
            {
                this.fetchOptions = fetchOptions;
            }


            public FetchOptions FetchOptions
            {
                get { return fetchOptions; }
            }
        }

        public class SelectedEventArgs : EventArgs
        {
            DataSourceSelectArguments data;
            IEnumerable result;
            private string sortExpression;
            private SortDirection sortDirection;


            public SelectedEventArgs(DataSourceSelectArguments data, IEnumerable result, string sortExpression, SortDirection sortDirection)
            {
                this.data = data;
                this.result = result;
                this.sortExpression = sortExpression;
                this.sortDirection = sortDirection;
            }

            public DataSourceSelectArguments Data
            {
                get { return data; }
            }

            public IEnumerable Result
            {
                get { return result; }
            }


            public string SortExpression
            {
                get { return sortExpression; }
            }

            public SortDirection SortDirection
            {
                get { return sortDirection; }
            }
        }

        public event EventHandler<PreSelectEventArgs> SelectPreExecute;
        public event EventHandler<SelectedEventArgs> SelectExecuted;

        private string sortExpression = string.Empty;
        private SortDirection sortDirection = SortDirection.Ascending;



        public BaseDataSourceView(IDataSource owner, string viewName)
            : base(owner, viewName)
        {
        }

        public string SortExpression
        {
            get { return sortExpression; }
            set { sortExpression = value; }
        }

        public SortDirection SortDirection
        {
            get { return sortDirection; }
            set { sortDirection = value; }
        }

        protected override IEnumerable ExecuteSelect(DataSourceSelectArguments arguments)
        {
            #region AddSupportedCapabilities

            if (this.CanSort)
            {
                arguments.AddSupportedCapabilities(DataSourceCapabilities.Sort);
            }
            if (this.CanPage)
            {
                arguments.AddSupportedCapabilities(DataSourceCapabilities.Page);
            }
            if (this.CanRetrieveTotalRowCount)
            {
                arguments.AddSupportedCapabilities(DataSourceCapabilities.RetrieveTotalRowCount);
            }

            #endregion

            if (arguments.RetrieveTotalRowCount)
            {
                //arguments.TotalRowCount = service.Count(); //result.Count;
                arguments.TotalRowCount = Count(); //result.Count;
                if (arguments.TotalRowCount <= arguments.StartRowIndex + 1)
                    arguments.StartRowIndex = (arguments.TotalRowCount / arguments.MaximumRows) *
                        arguments.MaximumRows;
            }

            FetchOptions fetchOptions = new FetchOptions();

            fetchOptions.FirstResult = arguments.StartRowIndex;
            fetchOptions.MaxResults = arguments.MaximumRows;
            fetchOptions.SortExpression = this.sortExpression;
            fetchOptions.SortDirection = this.sortDirection;

            FirePreSelect(fetchOptions);

            //ICollection<TestEntity> result = service.Find(fetchOptions);
            IEnumerable result = Find((FetchOptions)fetchOptions.Clone());

            FireSelectExecuted(arguments, result, this.sortExpression, this.sortDirection);

            return result;
        }

        protected void FireSelectExecuted(DataSourceSelectArguments arguments, IEnumerable result, string sortExpression, SortDirection sortDirection)
        {
            if (SelectExecuted != null)
                SelectExecuted(this, new SelectedEventArgs(arguments, result, sortExpression, sortDirection));

        }

        protected void FirePreSelect(FetchOptions fetchOptions)
        {
            if (SelectPreExecute != null)
            {
                SelectPreExecute(this, new PreSelectEventArgs(fetchOptions));
                this.sortExpression = fetchOptions.SortExpression;
                this.sortDirection = fetchOptions.SortDirection;
            }

        }

        protected abstract IEnumerable Find(FetchOptions fetchOptions);
        protected abstract int Count();

        public override bool CanSort
        {
            get { return true; }
        }

        ///<summary>
        ///Gets a value indicating whether the <see cref="T:System.Web.UI.DataSourceView"></see> object associated with the current <see cref="T:System.Web.UI.DataSourceControl"></see> object supports paging through the data retrieved by the <see cref="M:System.Web.UI.DataSourceView.ExecuteSelect(System.Web.UI.DataSourceSelectArguments)"></see> method.
        ///</summary>
        ///
        ///<returns>
        ///true if the operation is supported; otherwise, false. The base class implementation returns false.
        ///</returns>
        ///
        public override bool CanPage
        {
            get { return true; }
        }

        public override bool CanRetrieveTotalRowCount
        {
            get { return true; }
        }
    }
}
